//
// Created by  ta&to on 2022/10/9.
//

#include "http_handler.h"
static int _request_do(struct http_socket_event_loop_s *hset, http_fd_t *fds, int status){
    mutex_lock(&hset->hgdefc->event_fun_lock);
    noder node = RBtreenodesel(&hset->hgdefc->func_handler, fds->fdc);
    if(ISNULL(node)) thread_err;
    http_socket_event_handle_t * handler = (http_socket_event_handle_t *)node->spot->value;
    mutex_unlock(&hset->hgdefc->event_fun_lock);

    switch (status) {
        case HTTP_SOCKET_OPEN: {
            dts headstr = NULL;

            mutex_lock(&hset->hgdc->req_maps_header_lock);
            noder headnode = RBtreenodesel(&hset->hgdc->req_maps_header, fds->fdc);
            headstr = ISNULL(headnode)? dtsempty():(dts)headnode->spot->value;
            unsigned int oldsize = dtslen(headstr);
            headstr = dtscat(headstr, handler->data);
            do{             // 只要有修改的可能就要删除再添加，防止野指针问题
                RBtreenodedel(&hset->hgdc->req_maps_header, fds->fdc);
            } while (!RBtreenodeadd(&hset->hgdc->req_maps_header, fds->fdc, headstr));
            mutex_unlock(&hset->hgdc->req_maps_header_lock);

            unsigned int splitsize = handler->data_len;
            int len = indexof(headstr, HEADER_END_TARGET);
            if(len != -1) {                     // 说明已经找到请求头的结束标志
                splitsize = len + strlen(HEADER_END_TARGET);         // 这里把结束标志也截取出来

                mutex_lock(&fds->lock);
                getData(hset->logs, fds->fd, handler->data, splitsize - oldsize);// 真实读 这次读一定是成功的并且不会越界 读出的数据并不会被使用 只是为了清理读缓存
                mutex_unlock(&fds->lock);

                mutex_lock(&hset->hgdc->req_maps_header_lock);
                dtsrange(headstr, 0, splitsize);
                do{
                    RBtreenodedel(&hset->hgdc->req_maps_header, fds->fdc);
                } while (!RBtreenodeadd(&hset->hgdc->req_maps_header, fds->fdc, headstr));
                mutex_unlock(&hset->hgdc->req_maps_header_lock);

                http_inner_request_after_facade_t *hirqaft = (http_inner_request_after_facade_t *) http_malloc(sizeof(http_inner_request_after_facade_t));
                hirqaft->fds = fds;
                hirqaft->hset = hset;
                requst_control(hirqaft);
                return TRUE;
            } else {
                mutex_lock(&fds->lock);
                getData(hset->logs, fds->fd, handler->data, splitsize - 1);// 真实读 这次读一定是成功的并且不会越界 读出的数据并不会被使用 只是为了清理读缓存
                mutex_unlock(&fds->lock);
                return FALSE;
            }
        }
        case HTTP_SOCKET_CLOSE: {
            close_http(hset, fds);
            break;
        }
    }
}
static void _before_request_cycle(void *args, thread_task_args_t *args_t) {
    http_inner_request_before_facade_t *hirqbft = (http_inner_request_before_facade_t *)args;
    int ret,fd = hirqbft->fd;
    struct http_fd_s *fds = hirqbft->fds;
    struct http_socket_event_loop_s *hset = hirqbft->hset;
    http_free(hirqbft);                                     // 回收容器
    do{
        mutex_lock(&hset->hgdefc->event_fun_lock);
        noder node = RBtreenodesel(&hset->hgdefc->func_handler, fds->fdc);
        if(ISNULL(node)) return;
        http_socket_event_handle_t * handler = (http_socket_event_handle_t *)node->spot->value;
        mutex_unlock(&hset->hgdefc->event_fun_lock);

        mutex_lock(&fds->lock);
        ret = vgetData(hset->logs, fd, handler->data,handler->data_len - 1);// 虚读
        mutex_unlock(&fds->lock);
        //如果客户端主动断开连接，会进行四次挥手，会出发一个信号，此时相应的套接字会有数据返回，告诉select，我的客户断开了，你返回-1
        if(ret > 0){                                                    // 有相应的数据发送过来 ，进行相应的处理
            if(ret < handler->data_len)
                memset(&handler->data[ret],'\0',1);
            if(_request_do(hset, fds, HTTP_SOCKET_OPEN))
                return;
        }else if(ret == 0){
            _request_do(hset, fds, HTTP_SOCKET_CLOSE);                   // 任务结束
        }else if(ret == -1 && errno == EAGAIN) {
            continue;                                                   //  再试一次
        }else{
            error(hset->logs, "_before_request_cycle : %s", strerror(errno));
        }
     } while (ret > 0);
}

#ifdef SOCKET_SERVER_SELECT
void __socket_r_callback(struct http_socket_event_loop_s *hset, int fd, int n) {
#else
void __socket_r_callback(struct http_socket_event_loop_s *hset, int fd) {
#endif
    http_inner_request_before_facade_t *hirqbft = (http_inner_request_before_facade_t *)http_malloc(sizeof(http_inner_request_before_facade_t));
#ifdef SOCKET_SERVER_SELECT
    hirqbft->n = n;
#endif
    hirqbft->fd = fd;
    hirqbft->hset = hset;

    char *fdc = (char *) http_calloc(sizeof(char) * http_numlen(fd) + 1);

    memset(fdc, 0, sizeof(fdc));
    http_sprintf(fdc, "%d", fd);

    mutex_lock(&hset->hgdc->req_maps_fds_lock);
    noder fdNode = RBtreenodesel(&hset->hgdc->req_maps_fds, fdc);
    if(ISNULL(fdNode)) {
        struct http_fd_s *fds = (struct http_fd_s *) http_malloc(sizeof(struct http_fd_s));
        init_lock(&fds->lock);
        fds->fd = fd;
        fds->fdc = fdc;
        fds->state = FD_USE;
        hirqbft->fds = fds;
        RBtreenodeadd(&hset->hgdc->req_maps_fds, fdc, fds);
    } else {
        mutex_unlock(&hset->hgdc->req_maps_fds_lock);
        http_free(fdc);
        http_free(hirqbft);
        return;
    }
    mutex_unlock(&hset->hgdc->req_maps_fds_lock);

    Thread_Task_Post(hset->hgdc->tpt, _before_request_cycle, hirqbft);
}
void __socket_w_callback(struct http_socket_event_loop_s *hset, int fd){
    close(fd);
}
void close_http(struct http_socket_event_loop_s *hset, http_fd_t *fds) {
    if(ISNULL(hset) || ISNULL(fds))
        return;
    debug(hset->logs, "close_http():即将释放资源%s", fds->fdc);
    mutex_lock(&hset->hgdc->req_maps_fds_lock);
    noder nodefds = RBtreenodesel(&hset->hgdc->req_maps_fds, fds->fdc);
    if(ISNOTNULL(nodefds)) {
        RBtreenodedel(&hset->hgdc->req_maps_fds, fds->fdc); // 删掉容器中的队列
    }else{
        warn(hset->logs, "close_http():无法释放资源：没有找到资源句柄%s", fds->fdc);
    }
    mutex_unlock(&hset->hgdc->req_maps_fds_lock);

    mutex_lock(&hset->hgdc->req_maps_header_lock);
    noder nodeheader = RBtreenodesel(&hset->hgdc->req_maps_header, fds->fdc);
    if(ISNOTNULL(nodeheader)) {
        dtsfree(nodeheader->spot->value);
        RBtreenodedel(&hset->hgdc->req_maps_header, fds->fdc); // 删掉容器中的队列
    }else{
        warn(hset->logs, "close_http():无法释放资源：没有找到资源句柄%s", fds->fdc);
    }
    mutex_unlock(&hset->hgdc->req_maps_header_lock);
    free_func_handler(hset, fds);
    close(fds->fd);
    http_free(fds);
    http_free(fds->fdc);
    debug(hset->logs, "close_http():成功释放资源");
}


http_socket_event_handle_t *copy_func_handler(struct http_socket_event_loop_s *hset){
    http_socket_event_handle_t * handler= (http_socket_event_handle_t *) http_malloc(sizeof(http_socket_event_handle_t));
    handler->func_read = hset->hgdefc->temp_func_handler->func_read;
    handler->func_write = hset->hgdefc->temp_func_handler->func_write;
    handler->data = (char *) http_malloc(hset->hgdefc->temp_func_handler->data_len * sizeof(char));
    handler->data_len = hset->hgdefc->temp_func_handler->data_len;
    handler->sin_size = sizeof(struct sockaddr_in);
    return handler;
}

void free_func_handler(struct http_socket_event_loop_s *hset, http_fd_t *fds) {
    mutex_lock(&hset->hgdefc->event_fun_lock);
    noder node = RBtreenodesel(&hset->hgdefc->func_handler, fds->fdc);
    http_socket_event_handle_t * handler = (http_socket_event_handle_t *)node->spot->value;
    if(ISNOTNULL(node)){
        http_free(handler->data);
        http_free(handler);
        RBtreenodedel(&hset->hgdefc->func_handler, fds->fdc);
    }else{
        warn(hset->logs, "free_func_handler()无法释放资源：没有找到资源句柄%s", fds->fdc);
    }
    mutex_unlock(&hset->hgdefc->event_fun_lock);
}